package preSimulationWindow; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.DefaultCellEditor; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.border.Border; import simulation.SimProperties; import utils.Constants; @SuppressWarnings("serial") public class SimulationWindowPane extends JPanel { private ViewModel viewModel; private SpeciesTableModel tableModel; private boolean flag; // flag pour savoir si on est en vue simple ou // detaillee private Border sizePBorder; private Border popPBorder; private ArrayList<String> speciesList; // liste de toutes les especes private JComboBox speciesChoice; private ImageIcon addIcon; // icone pour ajouter des especes private ImageIcon removeIcon; // icone pour enlever des especes private ImageIcon infoIcon; // icone pour afficher les caracteristiques de // l'espece private JButton randomNumber; private JButton okButton; private JButton advancedParamsButton; private JComboBox gridSizeCombo; private JLabel gridHLabel; private JLabel gridWLabel; private JLabel gridComboLabel; private JPanel sizePanel; private JPanel popPanel; private JPanel buttonPanel; private JTable speciesTable; private JTextField gridHeight; private JTextField gridWidth; public SimulationWindowPane(ViewModel model) { viewModel = model; flag = false; addIcon = new ImageIcon(getClass().getResource("/add.png")); removeIcon = new ImageIcon(getClass().getResource("/remove.png")); infoIcon = new ImageIcon(getClass().getResource("/info.png")); tableModel = new SpeciesTableModel(); speciesList = new ArrayList<String>(); speciesList.add(""); for (String species : viewModel.getSpeciesList()) { speciesList.add(species); } speciesChoice = new JComboBox(speciesList.toArray()); speciesTable = new JTable(tableModel); this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); /******** Taille de la grille ********/ gridSizeCombo = new JComboBox(Constants.PREDEFINED_SIZES); gridSizeCombo.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { setGridSizeFromCombo(gridSizeCombo.getSelectedIndex()); } }); sizePanel = new JPanel(new GridBagLayout()); popPanel = new JPanel(new GridBagLayout()); buttonPanel = new JPanel(); gridHeight = new JTextField(); gridHeight.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { setCustomCombo(); } }); gridWidth = new JTextField(); gridWidth.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { setCustomCombo(); } }); gridHLabel = new JLabel("Hauteur : "); gridWLabel = new JLabel("Largeur : "); gridComboLabel = new JLabel("Tailles prédéfinies : "); /******** Population ********/ randomNumber = new JButton("Population aléatoire"); randomNumber.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { /** C'est le modele (ViewModel) qui va effectuer le calcul **/ randomAnimals(); } }); speciesTable.setShowGrid(false); speciesTable.setFillsViewportHeight(true); speciesTable.getColumnModel().getColumn(0) .setCellEditor(new DefaultCellEditor(speciesChoice)); speciesTable.getColumnModel().getColumn(1) .setCellEditor(new DefaultCellEditor(new JTextField())); speciesTable.getColumnModel().getColumn(2) .setCellRenderer(new ButtonRenderer(addIcon)); speciesTable.getColumnModel().getColumn(2) .setCellEditor(new ButtonEditor(addIcon, new ActionListener() { // Ajout d'une ligne @Override public void actionPerformed(ActionEvent e) { int idx = speciesTable.getEditingRow(); addRow(idx); } })); speciesTable.getColumnModel().getColumn(2).setMaxWidth(30); speciesTable.getColumnModel().getColumn(3) .setCellRenderer(new ButtonRenderer(removeIcon)); speciesTable .getColumnModel() .getColumn(3) .setCellEditor( new ButtonEditor(removeIcon, new ActionListener() { // Suppression d'une lignes @Override public void actionPerformed(ActionEvent e) { int idx = speciesTable.getEditingRow(); /** * Il faut arreter d'editer la ligne pour * pouvoir supprimer le bouton **/ /** * Car en fait je demande au botuon de supprimer * la ligne sur laquelle il se trouve **/ /** * Donc si je supprime la derniere ligne, ca va * buguer car Swing va vouloir repeindre la * derniere ligne **/ /** * A cause de l'editeur, mais y'a plus rien sauf * le bouton (etat instable....) **/ speciesTable.editingCanceled(null); removeRow(idx); } })); speciesTable.getColumnModel().getColumn(3).setMaxWidth(30); speciesTable.getColumnModel().getColumn(4) .setCellRenderer(new ButtonRenderer(infoIcon)); speciesTable.getColumnModel().getColumn(4) .setCellEditor(new ButtonEditor(infoIcon, new ActionListener() { // Ouverture de l'onglet d'informations @Override public void actionPerformed(ActionEvent e) { int row = speciesTable.getEditingRow(); String species = getSpecies(row); showInfos(species); } })); speciesTable.getColumnModel().getColumn(4).setMaxWidth(30); speciesTable.setRowHeight(30); /******** Boutons en bas de la fenetre : OK et changement de vue ********/ okButton = new JButton("OK"); okButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { Map<String, Integer> species = checkData(); if (species != null && species.size() > 0) { System.out.println("Paramétrage de la simulation terminé"); sendToModel(species); } } }); advancedParamsButton = new JButton("Vue détaillée"); advancedParamsButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (!flag) toggleAdvanced(); else toggleSimple(); } }); /******** Agencement dans la fenetre ********/ sizePBorder = BorderFactory.createTitledBorder("Taille de la grille"); popPBorder = BorderFactory.createTitledBorder("Population"); GridBagConstraints c = new GridBagConstraints(); sizePanel.setBorder(sizePBorder); c.gridx = 0; c.gridy = 0; c.gridwidth = 1; c.gridheight = 1; c.weighty = 0.2; c.fill = GridBagConstraints.HORIZONTAL; sizePanel.add(gridComboLabel, c); c.gridx = 1; c.weightx = 0.5; sizePanel.add(gridSizeCombo, c); c.gridx = 0; c.gridy = 1; c.gridwidth = 1; c.gridheight = 1; c.weightx = 0; c.weighty = 0.2; sizePanel.add(gridHLabel, c); gridHLabel.setVisible(false); c.gridx = 1; sizePanel.add(gridHeight, c); gridHeight.setVisible(false); c.gridx = 0; c.gridy = 2; c.gridwidth = 1; c.gridheight = 1; c.weighty = 0.2; sizePanel.add(gridWLabel, c); gridWLabel.setVisible(false); c.gridx = 1; sizePanel.add(gridWidth, c); gridWidth.setVisible(false); this.add(sizePanel); popPanel.setBorder(popPBorder); c.gridx = 0; c.gridy = 0; c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.CENTER; c.weightx = 0; c.weighty = 0; popPanel.add(randomNumber, c); c.gridx = 0; c.gridy = 1; c.gridwidth = 1; c.gridheight = 1; c.fill = GridBagConstraints.BOTH; c.weightx = 0.7; c.weighty = 0.7; popPanel.add(new JScrollPane(speciesTable), c); this.add(popPanel); buttonPanel.add(advancedParamsButton); buttonPanel.add(okButton); this.add(buttonPanel); setGridSizeFromCombo(0); } /** Permet de passer d'une vue simple a une vue detaillee **/ private void toggleAdvanced() { setSize(Constants.PRE_SIM_WDW_WIDTH, Constants.PRE_SIM_WDW_HEIGHT + 100); gridHLabel.setVisible(true); gridHeight.setVisible(true); gridWLabel.setVisible(true); gridWidth.setVisible(true); advancedParamsButton.setText("Vue simple"); flag = true; } /** Permet de passer d'une vue detaillee a une vue simple **/ private void toggleSimple() { setSize(Constants.PRE_SIM_WDW_WIDTH, Constants.PRE_SIM_WDW_HEIGHT); gridHLabel.setVisible(false); gridHeight.setVisible(false); gridWLabel.setVisible(false); gridWidth.setVisible(false); advancedParamsButton.setText("Vue detaillee"); flag = false; } /** Envoyer les donnees au modele et detruire la fenetre **/ private void sendToModel(Map<String, Integer> speciesList) { SimProperties properties = new SimProperties(); properties.setGridWidth(Integer.valueOf(gridWidth.getText())); properties.setGridHeight(Integer.valueOf(gridHeight.getText())); viewModel.sendToModel(speciesList, properties); /** Envoi de signal pour detruire la fenetre **/ firePropertyChange("launchSimulation", false, true); } private Map<String, Integer> checkData() { HashMap<String, Integer> speciesSim = new HashMap<String, Integer>(); String msg = ""; /** especes en doublons dans la simulation : affichage d'un message **/ ArrayList<String> speciesDuplicate = new ArrayList<String>(); /** especes avec une population erronee : affichage d'un message **/ ArrayList<String> speciesBadPop = new ArrayList<String>(); for (int row = 0; row < tableModel.getRowCount(); row++) { String species = getSpecies(row); int pop = getPop(row); if (!species.isEmpty()) { /** Si on a deja des especes dans la simulation **/ if (speciesSim.containsKey(species)) { /** Si l'espece est deja presente dans la simulation **/ speciesDuplicate.add(species); } else { if (pop == -1) /** S'il y a un probleme dans la population rentree par l'utilisateur **/ { if (!(speciesBadPop.contains(species))) speciesBadPop.add(species); } else speciesSim.put(species, pop); } } else { /** S'il y a un probleme dans la population rentree par l'utilisateur **/ if (!species.isEmpty() && pop == -1) speciesBadPop.add(species); else if (!species.isEmpty() ) speciesSim.put(species, pop); } } if (speciesDuplicate.isEmpty() && speciesBadPop.isEmpty()) return speciesSim; else { if (!speciesDuplicate.isEmpty()) { msg += "Attention, les espèces suivantes sont définies plusieurs fois : \n"; for (String str : speciesDuplicate) { msg += "- " + str + " ;\n"; } } if (!speciesBadPop.isEmpty()) { msg += "Attention, les populations des espèces suivantes sont mal définies : \n"; for (String str : speciesBadPop) { msg += "- " + str + " ;\n"; } } msg += "Veuillez corriger les données de la simulation"; JOptionPane.showMessageDialog(null, msg, "Warning", JOptionPane.WARNING_MESSAGE); } return null; } private void addRow(int idx) { tableModel.addRow(idx); /** * le fireTableRowsInserted continue a selectionner les lignes ajoutees, * d'ou le clearSelection() necessaire **/ speciesTable.clearSelection(); } private void removeRow(int idx) { tableModel.removeRow(idx); } private void showInfos(String species) { if (!species.isEmpty()) { String description = viewModel.getRestServer() .getSpeciesDescription(species); JOptionPane.showMessageDialog(null, description, "Informations sur l'espèce " + species, JOptionPane.INFORMATION_MESSAGE); } else { JOptionPane.showMessageDialog(null, "No species selected !", "Warning", JOptionPane.WARNING_MESSAGE); } } private void randomAnimals() { int tableSize = tableModel.getRowCount(); for (int i = 0; i < tableSize; i++) { if (!(getSpecies(i).isEmpty())) { int value = viewModel.randomAnimals(); tableModel.setValueAt(value, i, 1); } } } /*********************************** Getters ***********************************/ public int getGridWidth() { int res = -1; try { res = Integer.valueOf(gridWidth.getText()); } catch (Exception e) { System.out.println("largeur de la grille incorrecte"); res = -1; } return res; } public int getGridHeight() { int res = -1; try { res = Integer.valueOf(gridHeight.getText()); } catch (Exception e) { System.out.println("hauteur de la grille incorrecte"); res = -1; } return res; } /** Recupere le nom de l'espece comme ecrit dans la table **/ protected String getSpecies(int row) { return speciesTable.getValueAt(row, 0).toString(); } private int getPop(int row) { try { speciesTable.editingStopped(null); String value = speciesTable.getValueAt(row, 1).toString(); int pop = Integer.parseInt(value); if (pop <= 0) throw new Exception(); else return pop; } catch (Exception e) { return -1; } } /*********************************** Setters ***********************************/ public void setGridWidth(int w) { gridHeight.setText(Integer.toString(w)); } public void setGridHeight(int h) { gridWidth.setText(Integer.toString(h)); } public void setCustomCombo() { gridSizeCombo.setSelectedIndex(gridSizeCombo.getItemCount() - 1); } public JComboBox getGridSizeCombo() { return gridSizeCombo; } private void setGridSizeFromCombo(int idx) { if (idx == getGridSizeCombo().getItemCount() - 1) { toggleAdvanced(); } else { String size = Constants.PREDEFINED_SIZES[idx]; String[] array = size.split("x"); try { int width = Integer.valueOf(array[0]); setGridWidth(width); } catch (Exception e) { System.out.println("largeur de la grille incorrecte"); } try { int height = Integer.valueOf(array[1]); setGridHeight(height); } catch (Exception e) { System.out.println("hauteur de la grille incorrecte"); } } } public void updateSpecies() { speciesList.clear(); speciesList.add(""); for (String species : viewModel.getSpeciesList()) { speciesList.add(species); } speciesChoice = new JComboBox(speciesList.toArray()); speciesTable.getColumnModel().getColumn(0) .setCellEditor(new DefaultCellEditor(speciesChoice)); } }